#title: 工厂方法
#author:wendal(wendal1985@gmail.com)
#index:0,1
--------------------------------------------------------------------------------------------------------
什么是工厂方法?

	工厂方法,就是通过一个"虚拟"构造方法,供调用者获取特定的实例. 至于返回的是什么实例, 得看环境和传入的参数,及
	方法内的业务逻辑了.
	
	例如, 希望在生产环境用Product目录下的配置文件,开发环境用dev目录下的配置文件

--------------------------------------------------------------------------------------------------------
使用Iocbean的factory
	
	通过IocBean注解内的factory参数,可以自定义工厂类及工厂method
	
	factory参数的规则是, 以井号分隔,井号之前的是类名或ioc bean名称, 后面是方法名称.

	{{{<Java>
	@IocBean(factory="net.wendal.mqtt.MqttAbcServiceFactory#create", args={"refer:dao"})
	public class AbcService extends Service {
		...
		
	}
	
	// 无任何注解
	public class MqttAbcServiceFactory {
		public static AbcService create(Dao dao) {
			return new XXXXAbcService(dao);
		}
	}
	}}}
	
	通过其他bean生成此bean, 区别就是用`$对象名称` 代替 上一个例子的类名
	
	{{{<Java>
	@IocBean(factory="$snakerConfigure#build")
	public class SnakerService{}
	
	
	@IocBean(name="snakerConfigure")
	public class SnakerConfigure {
		public SnakerService build() {
			return ....;
		}
	}
	}}}
	
--------------------------------------------------------------------------------------------------------
使用IocBean实例方法
	
	先看示例. 这个功能是1.r.62新增.
	
	相比@IocBean的factory参数, 这种方式是声明"其他"bean的生成, 而不是自身.
	
	{{{<JAVA>
@IocBean // 首先,它自己必须加@IocBean, 可以使用@IocBean/@Inject的全部功能.
public class MyBeanFactory {

    //@Inject
    //public PropertiesProxy conf; // 像普通对象那么注入任何你需要的东西,这个conf也可是其他IocBean类,但不能是这个类了,否则死循环了
    @IocBean
    public PropertiesProxy getConf() {
        if ("product".equals(System.getProperty("nutz.runmode"))) {
              return new PropertiesProxy("/etc/nutz/custom");
        } else {
        	return new PropertiesProxy("custom/");
        }
    }

    // 生成一个名为dataSource的bean. 命名规则是: IocBean(name=XXX) > 方法名去掉get/build后首字母小写.
    @IocBean
    public SimpleDataSource getDataSource(PropertiesProxy conf) {
        SimpleDataSource ds = new SimpleDataSource();
        ds.setJdbcUrl(conf.get("db.url", "jdbc:h2:mem:nutztest"));
        return ds;
    }
    
    @IocBean 
    public Dao buildDao(DataSource dataSource) { // 带参数, 默认是按类型注入
        return new NutDao(dataSource);
    }
    

    @IocBean(name="dao2") // 自定义bean的名字,这样方法名就随便起了
    public Dao xxxgetDao2(DataSource dataSource) {
        return new NutDao(dataSource);
    }
    

    @IocBean(name="dao3")
    public Dao xxyyy(@Inject("refer:dataSource")DataSource ds) { // 参数加@Inject,可以像属性加上@Inject一样注入值
        return new NutDao(ds);
    }
    
    @IocBean(name="dao3", create="init", depose="depose") // 事件也是支持的
    public UserService makeUserService(Dao dao) {
        return new UserServiceImpl(dao);
    }
}
	}}}
	
	优缺点
	
	* 可以完全不使用js进行ioc配置
	* 可以更灵活地根据配置信息生成对象
	* 通过这种方式生成的对象,暂不支持Aop注入